package com.mallcai.bigdata.ladon.service.system.impl;

import com.cake.bigdata.starter.exception.category.BusinessException;
import com.mallcai.bigdata.ladon.dpl.entity.report.Report;
import com.mallcai.bigdata.ladon.dpl.entity.system.Resource;
import com.mallcai.bigdata.ladon.dpl.entity.system.Role;
import com.mallcai.bigdata.ladon.dpl.entity.system.RoleRlReport;
import com.mallcai.bigdata.ladon.dpl.entity.system.RoleRlResource;
import com.mallcai.bigdata.ladon.dpl.mapper.report.ReportMapper;
import com.mallcai.bigdata.ladon.dpl.mapper.system.ResourceMapper;
import com.mallcai.bigdata.ladon.dpl.mapper.system.RoleMapper;
import com.mallcai.bigdata.ladon.dpl.mapper.system.RoleRlReportMapper;
import com.mallcai.bigdata.ladon.dpl.mapper.system.RoleRlResourceMapper;
import com.mallcai.bigdata.ladon.service.system.IRoleService;
import com.mallcai.bigdata.ladon.utils.MaskUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.util.Assert;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by oneape<oneape15@163.com>
 * Created 2019-06-21 20:07.
 * Modify:
 */
@Slf4j
@Service
public class RoleService implements IRoleService {

    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private ResourceMapper resourceMapper;
    @Autowired
    private ReportMapper reportMapper;
    @Autowired
    private RoleRlResourceMapper roleRlResourceMapper;
    @Autowired
    private RoleRlReportMapper roleRlReportMapper;

    /**
     * 根据条件查询角色列表
     *
     * @param params Map
     * @return List
     */
    @Override
    public List<Role> getByParams(Map<String, Object> params) {
        return roleMapper.getByParams(params);
    }

    /**
     * 获取所有角色列表
     *
     * @return List
     */
    @Override
    public List<Role> getAllRoles() {
        return roleMapper.getAllRoles();
    }

    /**
     * 添加角色
     *
     * @param role Role
     * @return int
     */
    @Transactional
    @Override
    public int addRole(Role role) {
        Assert.isTrue(StringUtils.isNotBlank(role.getName()), "角色名为空");
        Assert.isTrue(StringUtils.isNotBlank(role.getCode()), "角色编码为空");
        List<Role> roles = roleMapper.hasSame(role.getCode(), role.getName());
        if (roles != null && roles.size() > 0) {
            throw new BusinessException("角色名或角色编码已存在");
        }
        return roleMapper.insert(role);
    }

    /**
     * 修改角色
     *
     * @param role Role
     * @return int
     */
    @Override
    public int updateRole(Role role) {
        Assert.isTrue(role.getId() != null, "角色主键为空");
        Assert.isTrue(StringUtils.isNotBlank(role.getName()), "角色名为空");
        Assert.isTrue(StringUtils.isNotBlank(role.getCode()), "角色编码为空");
        List<Role> roles = roleMapper.hasSame(role.getCode(), role.getName());
        if (roles != null && roles.size() > 0) {
            for (Role r : roles) {
                if (!r.getId().equals(role.getId())) {
                    throw new BusinessException("角色名或角色编码已存在");
                }
            }
        }
        return roleMapper.update(role);
    }

    /**
     * 删除角色
     *
     * @param role Role
     * @return int
     */
    @Override
    public int deleteRole(Role role) {
        Assert.isTrue(role.getId() != null, "角色主键为空");
        return roleMapper.delete(role);
    }

    /**
     * 保存角色资源权限信息
     *
     * @param roleId  Long 角色Id
     * @param resMask Map 资源权限Map  key-资源Id, value - 权限Mask
     * @return int
     */
    @Transactional
    @Override
    public int saveRoleRes(Long roleId, Map<Long, List<Integer>> resMask) {
        Assert.isTrue(roleId != null, "角色主键为空");

        // 清空指定角色Id的所有旧权限
        roleRlResourceMapper.deleteByRoleId(roleId);

        // 添加新的角色权限
        if (resMask != null && resMask.size() > 0) {
            List<Resource> resources = resourceMapper.getByIds(new ArrayList<>(resMask.keySet()));
            // 资源都无效,直接返回成功
            if (resources == null || resources.size() == 0) {
                return 1;
            }

            List<RoleRlResource> newMask = new ArrayList<>();
            List<Long> resIds = new ArrayList<>();

            resources.forEach(r -> {
                // 添加本身, 父节点不加入
                if ((r.getParentId() != null && r.getParentId() > 0) && !resIds.contains(r.getId())) {
                    List<Integer> maskList = resMask.get(r.getId());
                    Integer mask = MaskUtils.getMask(maskList);
                    newMask.add(new RoleRlResource(roleId, r.getId(), mask));
                    resIds.add(r.getId());
                }
            });

            // 插入新的权限值
            newMask.forEach(m -> roleRlResourceMapper.insert(m));
        }

        return 1;
    }

    /**
     * 保存角色报表权限信息
     *
     * @param roleId    Long 角色Id
     * @param reportIds List 报表Id列表
     * @return int
     */
    @Override
    public int saveRoleReport(Long roleId, List<Long> reportIds) {
        Assert.isTrue(roleId != null, "角色主键为空");

        // 清空指定角色Id的所有旧报表权限
        roleRlReportMapper.deleteByRoleId(roleId);

        if (CollectionUtils.isEmpty(reportIds)) {
            return 1;
        }

        // 添加新的报表权限
        List<Report> reports = reportMapper.getNameByIds(reportIds);
        if (CollectionUtils.isEmpty(reports)) {
            return 1;
        }

        List<RoleRlReport> list = new ArrayList<>();
        reports.forEach(r -> list.add(new RoleRlReport(roleId, r.getId())));

        // 插入新值
        list.forEach(l -> roleRlReportMapper.insert(l));
        return list.size();
    }

    /**
     * 获取角色资源权限
     *
     * @param roleId Long
     * @return Map
     */
    @Override
    public Map<Long, List<Integer>> getRoleRes(Long roleId) {
        if (roleId == null) {
            return new HashMap<>();
        }

        List<Long> list = new ArrayList<>();
        list.add(roleId);

        return getRoleRes(list);
    }

    /**
     * 获取角色报表权限
     *
     * @param roleId Long
     * @return List
     */
    @Override
    public List<Long> getRoleReport(Long roleId) {
        return roleRlReportMapper.getReportIdByRoleId(roleId);
    }

    /**
     * 根据角色Id列表,获取资源
     *
     * @param roleIds List
     * @return Map
     */
    @Override
    public Map<Long, List<Integer>> getRoleRes(List<Long> roleIds) {
        List<RoleRlResource> roleRlResources = roleRlResourceMapper.getByRoleIds(roleIds);
        Map<Long, List<Integer>> masks = new HashMap<>();
        if (roleRlResources == null || roleRlResources.size() == 0) {
            return masks;
        }

        roleRlResources.forEach(rrr -> masks.put(rrr.getResId(), MaskUtils.getList(rrr.getMask())));
        return masks;
    }
}
